package com.tiger.userClient.http.apps;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.tiger.db.entity.*;
import com.tiger.mongodb.entity.AppHistory;
import com.tiger.mongodb.entity.AppVisitLog;
import com.tiger.userClient.Db;
import com.tiger.userClient.http.apps.type.AppCategoryRes;
import org.springframework.beans.BeanUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import java.time.Instant;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class AppService {
    private final Db db;
    private final MongoTemplate mongoTemplate;


    public AppService(Db db, MongoTemplate mongoTemplate) {
        this.db = db;
        this.mongoTemplate = mongoTemplate;
    }


    //获取用户可用的分类
    public List<AppCategoryRes> ableCategory(boolean isAuth, Long userId, String role) {
        LambdaQueryWrapper<AppCategory> wrap = new LambdaQueryWrapper<>();

        List<AppCategory> rows;

        if(isAuth) {
            List<DictionaryItem> items = db.dictionaryItem.getItemsByCategory("PORTAL_USER_TYPE");

            Optional<DictionaryItem> item = items.stream() // 将List转换为流
                    .filter(v -> Objects.equals(v.getCode(), role)).findFirst();

            Long[] relateds = {item.get().getId()};

            rows = db.appCategory.selectAvailableCategoryByRelateds(relateds); //获取有权限的最顶级的分类


        }else {
            rows = db.appCategory.list(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getId, AppCategory::getName, AppCategory::getParentId, AppCategory::isAuth).eq(AppCategory::isAuth, false).eq(AppCategory::getTopId, 0).eq(AppCategory::isEnable, true).orderByDesc(AppCategory::getSort, AppCategory::getId));
        }

        //获取最顶部的分类下面的所有分类
        List<Integer> topIds = rows.stream().map(AppCategory::getId).collect(Collectors.toList());
        List<AppCategory> subRows = db.appCategory.list(new LambdaQueryWrapper<AppCategory>().in(AppCategory::getTopId, topIds).orderByDesc(AppCategory::getSort, AppCategory::getId));
        if(!subRows.isEmpty()) {
            rows.addAll(subRows);
        }



        List<AppCategoryRes> list = new ArrayList<>();
        for(AppCategory row : rows) {
            List<Integer> ids = new ArrayList<>();
            querySubCategory(rows, ids, row.getId());
            ids.add(row.getId());

            AppCategoryRes appCategoryRes = new AppCategoryRes();
            BeanUtils.copyProperties(row, appCategoryRes);
            appCategoryRes.setAppCount(db.app.count(new LambdaQueryWrapper<App>().in(App::getCategory, ids)));


            if(isAuth && row.getParentId() == 0) {
                String id = existsHistory(userId, row.getId());
                if(id != null) {
                    appCategoryRes.setHistoryId(id);
                }
            }

            list.add(appCategoryRes);
        }

        return list;
    }



    //查询所有子分类
    public void querySubCategory(List<AppCategory> categories, List<Integer> ids, int pid) {
        for(AppCategory cate : categories) {
            if(cate.getParentId() == pid) {
                ids.add(cate.getId());
                querySubCategory(categories, ids, cate.getId());
            }
        }
    }

    public List<App> historyApps(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(id));
        query.fields().include("data");
        AppHistory row = mongoTemplate.findOne(query, AppHistory.class);

        if(row != null && row.getData() != null && row.getData().length > 0) {
            return db.app.list(new LambdaQueryWrapper<App>().in(App::getId, row.getData()));
        }

        return null;

    }

    public String existsHistory(Long userId, Integer categoryId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("categoryId").is(categoryId).and("userId").is(userId));
        query.fields().include("_id");
        AppHistory row = mongoTemplate.findOne(query, AppHistory.class);

        return row == null ? null : row.getId();
    }

    //把访问加入历史
    @Async
    public void addHistory(Long appId, Long userId, String userKey) {
        Instant now = Instant.now();
        AppVisitLog log = new AppVisitLog();
        log.setAppId(appId);
        log.setUserId(userId);
        log.setUserKey(userKey);
        log.setCreateTime(now.getEpochSecond());
        mongoTemplate.insert(log);


        int categoryId = 0;
        App app = db.app.getOne(new LambdaQueryWrapper<App>().select(App::getCategory).eq(App::getId, appId));
        AppCategory category = db.appCategory.getOne(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getParentId, AppCategory::getTopId).eq(AppCategory::getId, app.getCategory()));
        if(category.getTopId() == 0) {
            categoryId = app.getCategory();
        }else {
            AppCategory cate = db.appCategory.getOne(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getId).eq(AppCategory::getId, category.getTopId()));
            categoryId = cate.getId();
        }

        Query query = new Query();
        query.addCriteria(Criteria.where("categoryId").is(categoryId).and("userId").is(userId));

        Update update = new Update();
        update.addToSet("data", appId);

        mongoTemplate.upsert(query, update, AppHistory.class);
    }

    //服务数据统计
    @Async
    public void statistics(boolean isAuth, Long appId, Long userId) {
        _statistics(isAuth, appId, userId);
    }

    @Transactional
    protected boolean _statistics(boolean isAuth, Long appId, Long userId) {
        // 获取当前日期
        LocalDate nowDate = LocalDate.now();

        // 分别获取年和月
        String year = String.valueOf(nowDate.getYear());
        String month = year + String.valueOf(nowDate.getMonthValue());



        Instant now = Instant.now();
        long time = now.getEpochSecond();


        LambdaUpdateWrapper<App> wrapperApp = new LambdaUpdateWrapper<>();
        wrapperApp.eq(App::getId, appId);

        App app = db.app.getOne(new LambdaQueryWrapper<App>().select(App::getVisitors, App::getUniqueVisitors, App::getVisitTimes, App::getCategory).eq(App::getId, appId));
        if(app == null) return false;



        AppCategory category = db.appCategory.getOne(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getVisitors, AppCategory::getUniqueVisitors, AppCategory::getVisitTimes, AppCategory::getTopId).eq(AppCategory::getId, app.getCategory()));
        if(category == null) return false;


        wrapperApp.set(App::getVisitors, app.getVisitors() + 1);//人次
        wrapperApp.set(App::getVisitTimes, app.getVisitTimes() + 1);//次数

        if(isAuth) {
            //查询是否已经访问过改应用
            AppVisitor had1 = db.appVisitor.getOne(new LambdaQueryWrapper<AppVisitor>().select(AppVisitor::getId).eq(AppVisitor::getAppId, appId).eq(AppVisitor::getUserId, userId));
            if(had1 == null) {
                wrapperApp.set(App::getUniqueVisitors, app.getUniqueVisitors() + 1);//人数

                AppVisitor appVisitor = new AppVisitor();
                appVisitor.setAppId(appId);
                appVisitor.setUserId(userId);
                appVisitor.setCreateTime(time);

                boolean r = db.appVisitor.save(appVisitor);
                if(!r) return false;
            }
        }

        boolean r1 = db.app.update(wrapperApp);
        if(!r1) return false;


        LambdaUpdateWrapper<AppCategory> wrapperCategory = new LambdaUpdateWrapper<>();
        wrapperCategory.eq(AppCategory::getId, app.getCategory());
        wrapperCategory.set(AppCategory::getVisitors, category.getVisitors() + 1);//人次
        wrapperCategory.set(AppCategory::getVisitTimes, category.getVisitTimes() + 1);//次数

        AppCategoryVisitor had2 = null;
        if(isAuth) {
            had2 = db.appCategoryVisitor.getOne(new LambdaQueryWrapper<AppCategoryVisitor>().select(AppCategoryVisitor::getId).eq(AppCategoryVisitor::getCategory, app.getCategory()).eq(AppCategoryVisitor::getUserId, userId));

            if(had2 == null) {
                wrapperCategory.set(AppCategory::getUniqueVisitors, category.getUniqueVisitors() + 1);//人数

                AppCategoryVisitor appCategoryVisitor = new AppCategoryVisitor();
                appCategoryVisitor.setCategory(app.getCategory());
                appCategoryVisitor.setUserId(userId);
                appCategoryVisitor.setCreateTime(time);

                boolean r = db.appCategoryVisitor.save(appCategoryVisitor);
                if(!r) return false;
            }
        }

        boolean r2 = db.appCategory.update(wrapperCategory);
        if(!r2) return false;

        if(category.getTopId() != 0) {
            AppCategory top = db.appCategory.getOne(new LambdaQueryWrapper<AppCategory>().select(AppCategory::getVisitors, AppCategory::getUniqueVisitors, AppCategory::getVisitTimes).eq(AppCategory::getId, category.getTopId()));

            LambdaUpdateWrapper<AppCategory> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(AppCategory::getId, category.getTopId());

            wrapper.set(AppCategory::getVisitors, top.getVisitors() + 1);//人次
            wrapper.set(AppCategory::getVisitTimes, top.getVisitTimes() + 1);//次数

            if(isAuth && had2 == null) {
                wrapper.set(AppCategory::getUniqueVisitors, top.getUniqueVisitors() + 1);
            }

            boolean r = db.appCategory.update(wrapper);
            if(!r) return false;
        }

        //月份
        AppVisitMonthStatistic monthStatistic = db.appVisitMonthStatistic.getOne(new LambdaQueryWrapper<AppVisitMonthStatistic>().eq(AppVisitMonthStatistic::getMonth, month).eq(AppVisitMonthStatistic::getAppId, appId));
        if(monthStatistic == null) {
            monthStatistic = new AppVisitMonthStatistic();
            monthStatistic.setAppId(appId);
            monthStatistic.setMonth(month);
            monthStatistic.setVisitors(1);
            monthStatistic.setVisitTimes(1);

            boolean r = db.appVisitMonthStatistic.save(monthStatistic);
            if(!r) return false;

        }else {
            monthStatistic.setVisitTimes(monthStatistic.getVisitTimes() + 1);
            monthStatistic.setVisitors(monthStatistic.getVisitors() + 1);

            boolean r = db.appVisitMonthStatistic.updateById(monthStatistic);
            if(!r) return false;
        }

        //年份
        AppVisitYearStatistic yearStatistic = db.appVisitYearStatistic.getOne(new LambdaQueryWrapper<AppVisitYearStatistic>().eq(AppVisitYearStatistic::getYear, year).eq(AppVisitYearStatistic::getAppId, appId));
        if(yearStatistic == null) {
            yearStatistic = new AppVisitYearStatistic();
            yearStatistic.setAppId(appId);
            yearStatistic.setYear(year);
            yearStatistic.setVisitors(1);
            yearStatistic.setVisitTimes(1);

            boolean r = db.appVisitYearStatistic.save(yearStatistic);
            if(!r) return false;

        }else {
            yearStatistic.setVisitTimes(yearStatistic.getVisitTimes() + 1);
            yearStatistic.setVisitors(yearStatistic.getVisitors() + 1);

            boolean r = db.appVisitYearStatistic.updateById(yearStatistic);
            if(!r) return false;
        }

        return true;
    }
}
